﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BizzCommInterfaces;
using WCFTrays.WCFServer;
using System.ServiceModel;
using System.Reflection;

namespace WCFTrays
{
    public class WCFInbox : Tray, IInbox
    {
        private const char _separator = '|';
        private const char _parameterSeparator = ';';
        public string connString { get; set; }
        public string hostUrl { get; set; }
        public string selectMessageQuery { get; set; }
        public string markAsReadMessageQuery { get; set; }
        public WcfParameter[] selectParameters { get; set; }
        public List<WcfParameter> markAsReadParameters { get; set; }
        private BasicHttpBinding binding;
        EndpointAddress addr;
        private WcfMessage workingMsg;
        public WCFInbox()
            :base()
        {
            base._name = "WCFInboxProvider";
            binding = new BasicHttpBinding();
            workingMsg = null;
            hostUrl = "http://";
            connString = "Server=SERVIDOR;Database=BASEDEDATOS;Integrated Security=True";
        }


        #region IInbox Members

        public string codeMe()
        {
            string ret = connString + _separator + hostUrl + _separator + selectMessageQuery + _separator + markAsReadMessageQuery + _separator + _concreteName;
            ret += _separator;
            foreach (WcfParameter p in markAsReadParameters)
            {
                ret += p.ParameterName + _parameterSeparator + p.MatchingColumn + _parameterSeparator;
            }
            ret = ret.TrimEnd(_parameterSeparator);

            return ret;
        }

        public void decodeMe(string box)
        {
            string[] attr = box.Split(_separator);
            connString = attr[0];
            hostUrl = attr[1];
            selectMessageQuery = attr[2];
            markAsReadMessageQuery = attr[3];
            _concreteName = attr[4];
            string[] pars = attr[5].Split(_parameterSeparator);
            int pos = 0;
            markAsReadParameters = new List<WcfParameter>();
            while (pos < pars.Length-1)
            {
                markAsReadParameters.Add(new WcfParameter()
                {
                    ParameterName = pars[pos],
                    MatchingColumn = pars[pos+1]
                });
                pos++;
            }
            addr = new EndpointAddress(hostUrl);
        }

        public string getConcreteInboxName()
        {
             return _concreteName;
        }

        public void getConfigurationWindow()
        {
            WCFInboxConfigControl configWindow = new WCFInboxConfigControl(this);
            configWindow.ShowDialog();
            try
            {
                addr = new EndpointAddress(hostUrl);
            }
            catch 
            {
                //Esto es por si el usuario ingresa una url invalida.
                //En esta ocación no se controla que la misma este bien formada
                //pero se evita que se caiga el sistema y/o que quede inconsistente
            }
        }

        public int getCount()
        {
            int count = 0;
            using (ServerManagerClient server = new ServerManagerClient(binding,addr))
            {
                count = server.getMessages(selectMessageQuery, selectParameters,connString).Count();
            }
            return count;
        }

        public string[] getDescription()
        {
            string[] ret = new string[5];
            ret[0] = "Cada mensaje será obtenido de un servidor WCF.";
            ret[1] = "";
            ret[2] = "Se debe configurar la consulta para obtener los mensajes, ejemplo: SELECT * FROM Mensajes.";
            ret[3] = "";
            ret[4] = "Se debe configurar la consulta para marcar los mensajes como leidos, ejemplo: DELETE FROM Mensajes";
            


            return ret;
        }

        public string getInboxName()
        {
            return _name;
        }

        public string getWorkingMessage()
        {
            string msgIdStr = null;
            using (ServerManagerClient server = new ServerManagerClient(binding, addr))
            {
                workingMsg = server.getMessages(selectMessageQuery, selectParameters,connString).FirstOrDefault();
                if (workingMsg != null)
                    msgIdStr = workingMsg.MensajeId.ToString();
            }
            return msgIdStr;
        }

        public bool isReady()
        {
            return (connString != null && selectMessageQuery != null && markAsReadMessageQuery != null && hostUrl != null && _concreteName != null);
        }

        public void markAsRead()
        {
            try
            {
                using (ServerManagerClient server = new ServerManagerClient(binding, addr))
                {
                    if (markAsReadParameters != null)
                    {
                        Type t = workingMsg.GetType();
                        foreach (WcfParameter p in markAsReadParameters)
                        {
                            var prop = t.GetProperties().Where(met => met.Name.ToUpper().Contains(p.MatchingColumn.ToUpper())).FirstOrDefault();
                            p.ParameterValue = prop.GetValue(workingMsg, null).ToString();
                        }

                    }
                    server.markMessageAsRead(markAsReadMessageQuery, markAsReadParameters.ToArray(),connString);
                }
            }
            catch (Exception ex)
            {

            }
        }

        public BizzMessage readMessage(string messageToRead)
        {
            BizzMessage retMsg = new BizzMessage();
            retMsg.Title = workingMsg.Titulo;
            List<WcfMsgAttribute> msgServerAttribList = null;


            using (ServerManagerClient server = new ServerManagerClient(binding, addr))
            {
                msgServerAttribList = server.getMessageAttributes(workingMsg.MensajeId,connString).ToList<WcfMsgAttribute>();
            }

            retMsg.Attributes = new List<MsgAttribute>();
            foreach (WcfMsgAttribute attrib in msgServerAttribList)
            {
                retMsg.Attributes.Add(new MsgAttribute()
                {
                    Name = attrib.AttrName,
                    Type = retMsg.getMsgType(attrib.AttrType),
                    Value = attrib.AttrValue
                });
            }

            return retMsg;
        }

        public void setConcreteInboxName(string name)
        {
            _concreteName = name;
        }

        #endregion

        
       
    }
}
